package www.reagnetbox.com.scan;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;

import java.io.IOException;
import java.util.Collection;

/**
 * Created by lgz on 17-5-2.
 */

public class UsbAbility extends CommAbility implements CommResCode {
	private UsbCommDev mDev;
	private Context mContext;
	private int rcvSize = 0;
	protected UsbDevice usbDevice;
	protected int usbId;
	protected UsbDeviceConnection deviceConnection;
	protected UsbEndpoint outEndPoint;
	protected UsbEndpoint inEndPoint;
	protected UsbInterface usbInterface;
	protected boolean bGetOutPoint = false;
	protected boolean bGetInPoint = false;


	private UsbAbility() {

	}

	public UsbAbility(Context context, UsbCommDev dev) {
		mContext = context;
		mDev = dev;
	}

	@Override
	public int sendData(byte[] data) {

		return sendDataBlock(data, 100);
	}

	@Override
	public int sendDataBlock(byte[] data, int timeOut) {

		if (isConnected && mDev.bEnableWrite) {
			return deviceConnection.bulkTransfer(outEndPoint, data, data.length, timeOut);
		}
		return -1;
	}


	@Override
	public byte[] recvDataLock(int timeOut) {
		if (!mDev.bEnableRead) {
			return null;
		}
		if (deviceConnection != null) {
			byte[] buf = new byte[0x2000];
			int ret = 0;

			if(rcvSize == 0) {
				rcvSize = 0x2000;
			}
			ret = deviceConnection.bulkTransfer(inEndPoint, buf, rcvSize, timeOut);

			if (ret > 0) {

				byte[] data = new byte[ret];
				System.arraycopy(buf, 0, data, 0, ret);

				return data;
			}

		}
		return null;


	}

	@Override
	public void open() throws IOException {
		LogComm.printf("usb comm open");
		if (isConnected) {
			return;
		}

		UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
		Collection<UsbDevice> devices = usbManager.getDeviceList().values();
		LogComm.printf("getDeviceList:" + devices.size());
		if (devices != null && devices.size() > 0) {
			for (UsbDevice device : devices) {
				setupDevice(device);
			}
		} else {
			throw new IOException("no device detect");
		}
	}


	void setupDevice(UsbDevice device) throws IOException {

		UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
		String devName;
		int procId = device.getProductId();
		int vendorId = device.getVendorId();

		if (mDev == null || mDev.getProcId() == null || mDev.getVendorId() == null) {
			throw new IOException("dev id err");
		}

		LogComm.printf("procId:" + procId + " vendorId:" + vendorId
				+ " ,dec pid:" + mDev.getProcId() + " ,dev vid:" + mDev.getVendorId());
		if (!mDev.getProcId().equals(procId + "")
				|| !mDev.getVendorId().equals(vendorId + "")) {
			return;
		}
		// if (InvoiceApp.bUsbConnect) {
		// return;
		// }
		int interfaceCount = device.getInterfaceCount();
		LogComm.printf("interfaceCount:" + interfaceCount);
//		if(usbInterface.getInterfaceClass() == 255
//				&& usbInterface.getInterfaceSubclass() == 255
//				&& usbInterface.getInterfaceProtocol() == 255){
//
//		}
		for (int i = 0; i < interfaceCount; i++) {
			usbInterface = device.getInterface(i);
			LogComm.printf("i:" + i + " getInterfaceClass:"
					+ usbInterface.getInterfaceClass()
					+ " getInterfaceSubclass:"
					+ usbInterface.getInterfaceSubclass()
					+ " getInterfaceProtocol:"
					+ usbInterface.getInterfaceProtocol());
			if (mDev.getInterfaceClass() != null) {
				if (!mDev.getInterfaceClass().equals(usbInterface.getInterfaceClass() + "")) {
					continue;
				}
			}
			if (mDev.getInterfaceClass() != null) {
				if (!mDev.getInterfaceSubclass().equals(usbInterface.getInterfaceSubclass() +
						"")) {
					continue;
				}
			}
			if (mDev.getInterfaceClass() != null) {
				if (!mDev.getInterfaceProtocol().equals(usbInterface.getInterfaceProtocol() +
						"")) {
					continue;
				}
			}
			usbDevice = device;
			devName = device.getDeviceName();
			int endpointCount = usbInterface.getEndpointCount();

			LogComm.printf("setup device:" + devName + " endpointCount:" + endpointCount);
//			if (endpointCount != 2) {
//				LogComm.printf("inteface endpoint count != 2");
//			}
			for (int j = 0; j < endpointCount; j++) {
				UsbEndpoint endpoint = usbInterface.getEndpoint(j);
				LogComm.printf("endpoint.getType:" + endpoint.getType() + " "
						+ endpoint.getDirection());
				if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
					if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
						outEndPoint = endpoint;
						bGetOutPoint = true;
					} else {
						inEndPoint = endpoint;
						bGetInPoint = true;
					}
				}
			}

			if (!bGetInPoint || !bGetOutPoint) {
				for (int j = 0; j < endpointCount; j++) {
					UsbEndpoint endpoint = usbInterface.getEndpoint(j);
					LogComm.printf("endpoint.getType:" + endpoint.getType() + " "
							+ endpoint.getDirection());
					if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
						if (!bGetOutPoint && endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
							outEndPoint = endpoint;
							bGetOutPoint = true;
						} else if (!bGetInPoint && endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
							inEndPoint = endpoint;
							rcvSize = inEndPoint.getMaxPacketSize();
							bGetInPoint = true;
						}
					}
				}
			}

			if (outEndPoint == null || inEndPoint == null) {
				throw new IOException("Not all needed endpoints found!");
			} else {
				if (usbManager.hasPermission(device)) {
					if (mDev.bEnableOpen) {
						deviceConnection = usbManager.openDevice(device);
						LogComm.printf("usbInterface:" + usbInterface
								+ " deviceConnection:" + deviceConnection);
						deviceConnection.claimInterface(usbInterface, true);
						usbId = deviceConnection.getFileDescriptor();
					}
					LogComm.printf("begin init:" + devName + " out:"
							+ outEndPoint.getAddress() + " out max size:"
							+ outEndPoint.getMaxPacketSize()
							+ " in max size:" + inEndPoint.getMaxPacketSize() + " in:"
							+ inEndPoint.getAddress() + " venId:"
							+ device.getVendorId() + " proId:"
							+ device.getProductId());
					isConnected = true;
				} else {
					PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
							new Intent(ACTION_USB_PERMISSION), 0);
					usbManager.requestPermission(device, pi);
					throw new IOException("need permission");
				}
			}
		}
	}

	@Override
	public void close() throws IOException {
		if (deviceConnection == null) {
			throw new IOException("Already closed");
		}

		deviceConnection.close();
		isConnected = false;
		deviceConnection = null;

	}


}
